package com.lcx.hw.filter;

import com.lcx.hw.pojo.CountVo;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.core.Ordered;
import org.springframework.core.io.buffer.DataBuffer;
import org.springframework.http.server.RequestPath;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;

import java.util.Arrays;
import java.util.List;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.TimeUnit;

@Component
public class RestrictInterfaceCounts implements GlobalFilter, Ordered {

    @Value("${lcx.min}")
    private Integer min;

    @Value("${lcx.count}")
    private Integer count;

    private static final String REGISTER = "isRegistered";

    private final ConcurrentHashMap<String, CountVo> map = new ConcurrentHashMap();


    /**
     * 限制单个客户端IP在最近X分钟内请求注册接⼝不能超过Y次
     * @param exchange
     * @param chain
     * @return
     */
    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        ServerHttpRequest request = exchange.getRequest();
        ServerHttpResponse response = exchange.getResponse();

        //ip
        String hostString = request.getRemoteAddress().getHostString();
        //请求路径
        String path = request.getPath().toString();
        String substring = path.substring(1);
        List<String> asList = Arrays.asList(substring.split("/"));
        //如果是注册接口
        if (asList.contains(REGISTER)){
            long newTime = System.currentTimeMillis();
            //判断是否已经有请求
            CountVo countVo = map.get(path);
            if (countVo != null){
                //判断当前时间与请求时间相比是否在一分钟之内
                Long oldTime = countVo.getSysTime();
                Integer countVoCount = countVo.getCount();
                long toMinutes = TimeUnit.MILLISECONDS.toMinutes(oldTime - newTime);
                if (toMinutes < min && countVoCount > count){
                    System.out.println("频繁进⾏注册");
                    String data = "错误码：303，错误信息：您频繁进⾏注册，请求已被拒绝";
                    DataBuffer wrap = response.bufferFactory().wrap(data.getBytes());
                    return response.writeWith(Mono.just(wrap));
                }else{
                    countVo.setSysTime(newTime).setCount(countVoCount + 1);
                    map.put(path,countVo);
                }
            }else{
                CountVo c = new CountVo();
                c.setCount(1).setSysTime(newTime);
                map.put(path,c);
            }
        }

        return chain.filter(exchange);
    }

    @Override
    public int getOrder() {
        return 0;
    }
}
